package com.black.service.aspect;

import com.alibaba.fastjson2.JSONObject;
import com.black.protocol.Response;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;

import java.lang.reflect.Method;

/**
 * @author ylx
 */
@Slf4j
@Aspect
@Component
public class ApiAspect {
    @Pointcut("@annotation(org.springframework.web.bind.annotation.PostMapping) || @annotation(org.springframework.web.bind.annotation.GetMapping)")
    public void api() {
    }

    @Around(value = "api()")
    public Object logAround(ProceedingJoinPoint pjp) {
        try {
            Object[] args = pjp.getArgs();
            log.debug("request:{} enter, param: {}", getUrl(pjp), JSONObject.toJSONString(args));
            Object result = pjp.proceed();
            log.debug("request:{} exit, result: {}", getUrl(pjp), JSONObject.toJSONString(result));
        } catch (Throwable throwable) {
            log.error("request:{} error", getUrl(pjp), throwable);
        }
        return Response.fail();
    }

    private String getUrl(JoinPoint joinPoint) {
        Method currentMethod = getCurrentMethod(joinPoint);
        if (currentMethod==null) {
            return null;
        }
        String url = null;
        if (currentMethod.isAnnotationPresent(PostMapping.class)) {
            PostMapping annotation = currentMethod.getAnnotation(PostMapping.class);
            url = String.join(",", annotation.value());
        } else if (currentMethod.isAnnotationPresent(GetMapping.class)) {
            GetMapping annotation = currentMethod.getAnnotation(GetMapping.class);
            url = String.join(",", annotation.value());
        }
        return url;
    }

    private Method getCurrentMethod(JoinPoint joinPoint) {
        Signature signature = joinPoint.getSignature();
        String methodName = signature.getName();
        Class<?>[] parameterTypes = ((org.aspectj.lang.reflect.MethodSignature) signature).getParameterTypes();
        try {
            return joinPoint.getTarget().getClass().getMethod(methodName, parameterTypes);
        } catch (NoSuchMethodException e) {
            log.error("获取当前方法失败", e);
            return null;
        }
    }
}
